/**
 * @file Utilities.hpp
 *
 *  @date 2009-06-05
 *  @author hauleth
 */

#ifndef UTILITIES_HPP_
#define UTILITIES_HPP_

#include <sstream>
#include <typeinfo>
#include <limits>
#include <iterator>

namespace bust {
namespace {

enum endian {
	LITTLE, BIG
};

endian Endianness() {
	int num = 10;
	if( *reinterpret_cast< char* > ( &num ) == 10 )
		return LITTLE;
	return BIG;
}

// --------------------------------- lexical cast ------------------------------------------
class bad_lexical_cast: public std::bad_cast {
	public:
		virtual const char* what() const throw() {
			return "Bad lexical cast";
		}
};

template < typename To, typename From >
To lexical_cast( const From& in ) {
	std::stringstream ss;
	To out;
	if( ! ( ss << in ) || ! ( ss >> out ) || ! ( ss >> std::ws ).eof() )
		throw bad_lexical_cast();
	return out;
}
// --------------------------------- class modifications -----------------------------------
class noncopyable {
		noncopyable( const noncopyable& );
		const noncopyable& operator=( const noncopyable& );
	protected:
		noncopyable() {
		}
		~noncopyable() {
		}
};

class nonheapable {
		void* operator new( size_t );
};

class nonaddressable: nonheapable {
		int operator&();
};

// ------------------------------------- addressof -----------------------------------------
template < typename T >
inline T* addressof( T& o ) {
	return reinterpret_cast< T* > ( &reinterpret_cast< char& > ( o ) );
}

template < typename T >
inline const T* addressof( const T& o ) {
	return reinterpret_cast< const T* > ( &reinterpret_cast< const char& > ( o ) );
}

template < typename T >
inline volatile T* addressof( volatile T& o ) {
	return reinterpret_cast< volatile T* > ( &reinterpret_cast< volatile char& > ( o ) );
}

template < typename T >
inline const volatile T* addressof( const volatile T& o ) {
	return reinterpret_cast< const volatile T* > ( &reinterpret_cast< const volatile char& > ( o ) );
}
// -------------------------------------prior & next ----------------------------------------
template < typename T >
inline T next( T iterator ) {
	return ++iterator;
}

template < typename T, typename Dist >
inline T next( T iterator, Dist distance ) {
	std::advance( iterator, distance );
	return iterator;
}

template < typename T >
inline T prior( T iterator ) {
	return --iterator;
}

template < typename T, typename Dist >
inline T prior( T iterator, Dist distance ) {
	std::advance( iterator, -distance );
	return iterator;
}

}
}

#endif /* UTILITIES_HPP_ */
